"""产品文档分块器

基于BaseChunker实现的产品文档专用分块器。
"""

import os
import re
import time
import threading
from typing import List, Tuple, Optional

import docx2txt
from docx import Document

from core.base_chunker import BaseChunker, ChunkingStrategy
from utils.logger import LoggerManager, ErrorHandler, log_execution_time, handle_exceptions
from config.settings import ConfigManager


class ProductChunkingStrategy(ChunkingStrategy):
    """产品文档专用分块策略"""
    
    def __init__(self, min_content_length: int = 50):
        self.min_content_length = min_content_length
        self.logger = LoggerManager.get_logger(self.__class__.__name__)
        
    def chunk(self, text: str) -> List[str]:
        """智能分块产品文档"""
        try:
            return self._smart_chunk_product_text(text)
        except Exception as e:
            self.logger.error(f"产品文档分块失败: {e}")
            # 降级到简单分块
            return self._fallback_chunk(text)
    
    def _smart_chunk_product_text(self, text: str) -> List[str]:
        """智能分块产品文档，考虑产品特性和功能模块"""
        lines = [line.strip() for line in text.split('\n') if line.strip()]
        
        chunks = []
        current_chunk = []
        
        # 产品文档特有的模式
        product_patterns = {
            'title': [
                r'^.*产品.*说明书.*$',
                r'^.*用户.*手册.*$',
                r'^.*操作.*指南.*$',
                r'^.*技术.*规格.*$'
            ],
            'section': [
                r'^第[一二三四五六七八九十\d]+[章节部分].*',
                r'^[一二三四五六七八九十]+[、.].*',
                r'^\d+[、.].*',
                r'^[A-Z]+[、.].*'
            ],
            'feature': [
                r'^.*功能.*[:：].*',
                r'^.*特性.*[:：].*',
                r'^.*特点.*[:：].*',
                r'^.*优势.*[:：].*'
            ],
            'specification': [
                r'^.*规格.*[:：].*',
                r'^.*参数.*[:：].*',
                r'^.*技术.*指标.*[:：].*',
                r'^.*性能.*参数.*[:：].*'
            ],
            'operation': [
                r'^.*操作.*步骤.*[:：].*',
                r'^.*使用.*方法.*[:：].*',
                r'^.*安装.*步骤.*[:：].*',
                r'^.*配置.*方法.*[:：].*'
            ]
        }
        
        i = 0
        while i < len(lines):
            line = lines[i]
            
            # 检查行类型
            line_type = self._classify_line(line, product_patterns)
            
            if line_type == 'title':
                # 标题单独成块
                if current_chunk:
                    chunks.append('\n'.join(current_chunk))
                    current_chunk = []
                chunks.append(line)
                i += 1
                
            elif line_type == 'section':
                # 章节标题开始新块
                if current_chunk:
                    chunks.append('\n'.join(current_chunk))
                    current_chunk = []
                
                # 收集整个章节内容
                section_content = [line]
                i += 1
                
                while i < len(lines):
                    next_line = lines[i]
                    next_type = self._classify_line(next_line, product_patterns)
                    
                    if next_type in ['title', 'section']:
                        break
                    
                    section_content.append(next_line)
                    i += 1
                
                if section_content:
                    chunks.append('\n'.join(section_content))
                
            elif line_type in ['feature', 'specification', 'operation']:
                # 功能、规格、操作等模块化内容
                if current_chunk:
                    chunks.append('\n'.join(current_chunk))
                    current_chunk = []
                
                # 收集模块内容
                module_content = [line]
                i += 1
                
                while i < len(lines):
                    next_line = lines[i]
                    next_type = self._classify_line(next_line, product_patterns)
                    
                    if next_type in ['title', 'section', 'feature', 'specification', 'operation']:
                        break
                    
                    module_content.append(next_line)
                    i += 1
                
                if module_content:
                    chunks.append('\n'.join(module_content))
                
            else:
                # 普通内容
                current_chunk.append(line)
                
                # 检查是否需要分块（基于长度）
                if len('\n'.join(current_chunk)) > self.min_content_length * 10:
                    chunks.append('\n'.join(current_chunk))
                    current_chunk = []
                
                i += 1
        
        # 添加最后一个块
        if current_chunk:
            chunks.append('\n'.join(current_chunk))
        
        return [chunk for chunk in chunks if chunk.strip()]
    
    def _classify_line(self, line: str, patterns: dict) -> str:
        """分类文本行"""
        for line_type, pattern_list in patterns.items():
            for pattern in pattern_list:
                if re.match(pattern, line, re.IGNORECASE):
                    return line_type
        return 'content'
    
    def _fallback_chunk(self, text: str) -> List[str]:
        """降级分块策略"""
        # 简单按段落分块
        paragraphs = [p.strip() for p in text.split('\n\n') if p.strip()]
        return [p for p in paragraphs if len(p) >= self.min_content_length]


class ProductTextChunker(BaseChunker):
    """产品文档分块器"""
    
    def __init__(self):
        super().__init__()
        self.config_manager = ConfigManager()
        self.logger = LoggerManager.get_logger(self.__class__.__name__)
        self.error_handler = ErrorHandler()
        
        # 设置窗口标题
        self.master.title("产品文档智能分块工具 v2.0")
        
        # 设置默认分块策略
        self.chunking_strategy = ProductChunkingStrategy()
        
        # 加载配置
        self._load_config()
    
    def _load_config(self):
        """加载配置"""
        try:
            config = self.config_manager.load_config()
            # 应用配置到UI
            self.min_content_length_var.set(config.chunking.min_content_length)
            self.timeout_var.set(config.processing.timeout)
        except Exception as e:
            self.logger.warning(f"加载配置失败，使用默认配置: {e}")
    
    @handle_exceptions
    @log_execution_time
    def extract_text_from_docx(self, file_path: str) -> str:
        """从DOCX文件提取文本"""
        text = ""
        extraction_errors = []
        
        # 方法1: 使用docx2txt
        try:
            self.log("尝试使用docx2txt提取文本...")
            text = docx2txt.process(file_path)
            if text and text.strip():
                self.log("docx2txt提取成功")
                return text
        except Exception as e:
            extraction_errors.append(f"docx2txt失败: {e}")
            self.logger.warning(f"docx2txt提取失败: {e}")
        
        # 方法2: 使用python-docx
        try:
            self.log("尝试使用python-docx提取文本...")
            doc = Document(file_path)
            paragraphs = []
            for paragraph in doc.paragraphs:
                if paragraph.text.strip():
                    paragraphs.append(paragraph.text.strip())
            
            text = '\n'.join(paragraphs)
            if text and text.strip():
                self.log("python-docx提取成功")
                return text
        except Exception as e:
            extraction_errors.append(f"python-docx失败: {e}")
            self.logger.warning(f"python-docx提取失败: {e}")
        
        # 如果所有方法都失败
        error_msg = "所有文本提取方法都失败:\n" + "\n".join(extraction_errors)
        raise Exception(error_msg)
    
    @handle_exceptions
    def process_file(self, file_path: str, output_dir: str, chunk_mode: str, 
                    separator: str, blank_line_count: int) -> int:
        """处理单个文件"""
        try:
            # 创建输出目录
            os.makedirs(output_dir, exist_ok=True)
            
            # 获取文件信息
            file_name = os.path.splitext(os.path.basename(file_path))[0]
            file_size = os.path.getsize(file_path) / 1024  # KB
            
            self.log(f"处理文件: {file_name}")
            self.log(f"文件大小: {file_size:.2f} KB")
            
            # 检查文件
            if not os.path.exists(file_path):
                raise FileNotFoundError(f"文件不存在: {file_path}")
            
            if file_size == 0:
                raise ValueError("文件内容为空")
            
            # 提取文本
            text = self.extract_text_from_docx(file_path)
            
            if not text or not text.strip():
                raise ValueError("提取的文本内容为空")
            
            self.log(f"提取文本长度: {len(text)} 字符")
            
            # 分块处理
            if chunk_mode == "智能分块":
                chunks = self.chunking_strategy.chunk(text)
            else:
                # 使用分隔符分块
                from core.base_chunker import SeparatorChunkingStrategy
                sep_strategy = SeparatorChunkingStrategy(separator)
                chunks = sep_strategy.chunk(text)
            
            self.log(f"分块完成，共 {len(chunks)} 个块")
            
            # 保存分块结果
            chunk_count = self._save_chunks(chunks, file_name, output_dir, blank_line_count)
            
            return chunk_count
            
        except Exception as e:
            self.error_handler.handle_processing_error(e, {"file_path": file_path})
            raise
    
    def _save_chunks(self, chunks: List[str], file_name: str, output_dir: str, 
                    blank_line_count: int) -> int:
        """保存分块结果"""
        output_format = self.output_format_var.get()
        blank_lines = '\n' * blank_line_count
        
        if output_format == "单个文件":
            # 保存到单个文件
            output_file = os.path.join(output_dir, f"{file_name}_chunked.txt")
            with open(output_file, 'w', encoding='utf-8') as f:
                f.write(blank_lines.join(chunks))
            self.log(f"保存到: {output_file}")
        else:
            # 保存到多个文件
            for i, chunk in enumerate(chunks, 1):
                output_file = os.path.join(output_dir, f"{file_name}_chunk_{i:03d}.txt")
                with open(output_file, 'w', encoding='utf-8') as f:
                    f.write(chunk)
            self.log(f"保存到 {len(chunks)} 个文件")
        
        return len(chunks)


def main():
    """主函数"""
    import tkinter as tk
    
    # 配置日志
    LoggerManager.setup_logging()
    
    # 创建应用
    root = tk.Tk()
    app = ProductTextChunker()
    
    # 运行应用
    root.mainloop()


if __name__ == "__main__":
    main()